package com.itheima.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
     *  JDK代理类 (JdkProxy) : 将通知应用到目标对象之后，被动态创建的对象。
     *  代理对象 : 经过“代理”这一过程，生成的类即为“代理对象”，也称为“增强功能后的目标对象”
     *  (可以理解为: “代理” / "代理类"的目的之一 : 生成“代理对象”)
     */
    public class JdkProxy implements InvocationHandler {

        //声明目标类接口
        private UserDao userDao;

        //创建代理方法  fddthbgbf
        public Object createProxy(UserDao userDao) {

            this.userDao = userDao;
            //1.类加载器 (JdkProxy的类加载器) ---获得JdkProxy对应的“类加载器”
            ClassLoader classLoader = JdkProxy.class.getClassLoader();
            //2.被代理对象实现的所有接口 (此处为: UserDao 的接口内容等。)
            Class[] clazz = userDao.getClass().getInterfaces();
            //3.使用代理类，进行增强，返回的是 ”代理后的对象“ / “增强功能后的目标对象”
            return Proxy.newProxyInstance(classLoader, clazz, this);
        }

        /**
         * @param proxy  被代理后的对象
         * @param method 将要执行的方法信息 (反射)
         * @param args   执行方法时需要的参数
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            /*
             声明切面类 (其中有要用在特定“切入点”的“通知”)
             切入点 : 要进行“增强处理”/被“通知” 的 方法名
             通知(也称“增强处理”): 切面类中的方法
             对切入点进行“增强处理” : 在某个方法被执行的前/后的时机执行切面中的“方法”
             */
            //创建切面类
            MyAspect myAspect = new MyAspect();

            /*
             *  目标方法执行的前后，会分别执行切面类中的 check_Permissions()方法 和 log()方法
             *  前增强 : 执行UserDao接口的方法之前先执行 切面类中的 check_Permissions()这个方法
             *  后增强 : 执行完接口的方法后执行log()这个方法
             */
            //前增强
            myAspect.check_Permissions();

            //在目标类上调用方法，并传入参数
            Object obj = method.invoke(userDao, args); //执行UserDao接口中的方法

            //后增强
            myAspect.log();

            return obj;
        }
    }

